/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package technotheist.data;

import technotheist.data.wrap.VecBuffer;

/**
 *
 * @author Mitch
 * @param <T>
 */
public abstract class BVec<T extends Number> implements BObj {

    @SuppressWarnings("unchecked")
    public static BVec createVec(VecBuffer src, int index, Size size) {
	if (src.primType() == Float.TYPE) {
	    return new BVecF((VecBuffer<Float>) src, index, size);
	} else if (src.primType() == Integer.TYPE) {
	    return new BVecI((VecBuffer<Integer>) src, index, size);
	} else if (src.primType() == Byte.TYPE) {
	    return new BVecB((VecBuffer<Byte>) src, index, size);
	}
	return null;
    }

    public static final int X = 0, Y = 1, Z = 2, W = 3;

    private final VecBuffer<T> owner;
    protected final int index;
    protected final int elems;

    public VecBuffer<T> owner() {
	return owner;
    }

    public BVec(VecBuffer<T> owner, int index, Size size) {
	this.owner = owner;
	this.index = index;
	this.elems = size.elems;
    }

    public void set(BVec<T> vec) {
	if (vec != this) {
	    for (int i = 0; i < elems(); i++) {
		s(i, vec.s(i));
	    }
	}
    }

    public static enum Size {

	n2(2), n3(3), n4(4), n8(8), n16(16);
	public final int elems;

	private Size(int size) {
	    this.elems = size;
	}

    }

    public static class BVecF extends BVec<Float> {

	public BVecF(VecBuffer<Float> owner, int index, Size size) {
	    super(owner, index, size);
	}

	@Override
	public int elems() {
	    return elems;
	}

	@Override
	public Float s(int s) {
	    return owner().src().s(index * elems + s);
	}

	@Override
	public void s(int s, Float val) {
	    owner().src().s(index * elems + s, val);
	}

    }

    public static class BVecI extends BVec<Integer> {

	public BVecI(VecBuffer<Integer> owner, int index, Size size) {
	    super(owner, index, size);
	}

	@Override
	public int elems() {
	    return elems;
	}

	@Override
	public Integer s(int s) {
	    return owner().src().s(index * elems + s);
	}

	@Override
	public void s(int s, Integer val) {
	    owner().src().s(index * elems + s, val);
	}

    }

    public static class BVecB extends BVec<Byte> {

	public BVecB(VecBuffer<Byte> owner, int index, Size size) {
	    super(owner, index, size);
	}

	@Override
	public int elems() {
	    return elems;
	}

	@Override
	public Byte s(int s) {
	    return owner().src().s(index * elems + s);
	}

	@Override
	public void s(int s, Byte val) {
	    owner().src().s(index * elems + s, val);
	}

    }

    public abstract int elems();

    public abstract T s(int s);

    public abstract void s(int s, T val);

    public T x() {
	return s(X);
    }

    public T y() {
	return s(Y);
    }

    public T z() {
	return s(Z);
    }

    public T w() {
	return s(W);
    }

    public void x(T val) {
	s(X, val);
    }

    public void y(T val) {
	s(Y, val);
    }

    public void z(T val) {
	s(Z, val);
    }

    public void w(T val) {
	s(W, val);
    }
}
